import {
  _decorator,
  Component,
  Node,
  input,
  Input,
  EventTouch,
  math,
  Prefab,
  instantiate,
  CCInteger,
  Collider2D,
  Contact2DType,
  Animation,
  director,
  AudioClip,
} from 'cc'
import { RewardType, Reward } from './Reward'
import { GameManager } from './GameManager'
import { LifeCountUI } from './UI/LifeCountUI'
import { AudioMgr } from './AudioMgr'
const { ccclass, property } = _decorator

enum ShootType {
  OneShoot,
  TwoShoot,
  None,
}

@ccclass('Player')
export class Player extends Component {
  private _limitPoisitionX: number = 230
  private _limitPoisitionY: number = 380
  // 发射频率
  @property({ type: CCInteger })
  shootRate: number = 0.3

  // 弹幕间隔
  shootTimer: number = 0

  // 子弹容器
  @property({ type: Node })
  bulletParent: Node = null

  // 子弹1预制体
  @property({ type: Prefab })
  bullet1Prefab: Prefab = null

  // 子弹1位置
  @property({ type: Node })
  bullet1Position: Node = null

  // 子弹2预制体
  @property({ type: Prefab })
  bullet2Prefab: Prefab = null

  // 子弹2位置
  @property({ type: Node })
  bullet2Position: Node = null

  // 子弹类型
  @property({ type: CCInteger })
  shootType: ShootType = ShootType.TwoShoot

  // 动画
  @property({ type: Animation })
  animation: Animation = null

  // 生命值
  @property({ type: CCInteger })
  hp: number = 3

  // 子弹音效
  @property({ type: AudioClip })
  bulletSound: AudioClip = null

  // 奖励twoshoot音效
  @property({ type: AudioClip })
  twoShootSound: AudioClip = null

  // 奖励bomb音效
  @property({ type: AudioClip })
  bombSound: AudioClip = null

  // 碰撞动画
  @property
  animationHit: string = ''

  // 死亡动画
  @property
  animationDown: string = ''

  // 两弹时间
  private _TwoShootTime = 10

  // 无敌时间
  @property({ type: CCInteger })
  private invincibleTime: number = 1
  private invincibleTimer: number = 0
  private isInvincible: boolean = false

  private _collider: Collider2D = null

  // 生命数
  @property(LifeCountUI)
  lifeCountUI: LifeCountUI = null

  protected start(): void {
    this.lifeCountUI.updateUI(this.hp)
  }
  protected onLoad() {
    input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this)
    this._collider = this.node.getComponent(Collider2D)
    if (this._collider) {
      this._collider.on(Contact2DType.BEGIN_CONTACT, this.onBegainContact, this)
    }
  }
  protected onDestroy(): void {
    input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this)
    if (this._collider) {
      this._collider.off(Contact2DType.BEGIN_CONTACT, this.onBegainContact, this)
    }
  }
  onTouchMove(event: EventTouch) {
    if (director.isPaused()) return
    if (this.hp > 0) {
      const position = this.node.getPosition()
      const targetX = math.clamp(
        position.x + event.getDeltaX(),
        -this._limitPoisitionX,
        this._limitPoisitionX,
      )
      const targetY = math.clamp(
        position.y + event.getDeltaY(),
        -this._limitPoisitionY,
        this._limitPoisitionY,
      )
      this.node.setPosition(targetX, targetY, position.z)
    }
  }
  update(deltaTime: number) {
    this.shootTimer += deltaTime
    if (this.shootTimer > this.shootRate) {
      this.shootTimer = 0
      switch (this.shootType) {
        case ShootType.OneShoot:
          this.oneShoot()
          break
        case ShootType.TwoShoot:
          this.TwoShoot()
          break
        default:
          break
      }
    }
    if (this.isInvincible) {
      this.invincibleTimer += deltaTime
      if (this.invincibleTimer > this.invincibleTime) {
        this.isInvincible = false
        this.invincibleTimer = 0
      }
    }
  }
  oneShoot() {
    AudioMgr.inst.playOneShot(this.bulletSound, 0.1)
    const bullet1 = instantiate(this.bullet1Prefab)
    this.bulletParent.addChild(bullet1)
    bullet1.setWorldPosition(this.bullet1Position.getWorldPosition())
  }
  TwoShoot() {
    AudioMgr.inst.playOneShot(this.bulletSound, 0.1)
    const bullet201 = instantiate(this.bullet2Prefab)
    const bullet202 = instantiate(this.bullet2Prefab)
    const bullet2Position = this.bullet2Position.getWorldPosition()
    this.bulletParent.addChild(bullet201)
    this.bulletParent.addChild(bullet202)
    bullet201.setWorldPosition(
      bullet2Position.x - 25,
      bullet2Position.y,
      bullet2Position.z,
    )
    bullet202.setWorldPosition(
      bullet2Position.x + 25,
      bullet2Position.y,
      bullet2Position.z,
    )
  }
  onBegainContact(_: Collider2D, otherCollider: Collider2D) {
    const reward = otherCollider.getComponent(Reward)
    if (reward) {
      this.onContactReward(reward)
    } else {
      this.onContactEnemy()
    }
  }
  reward: Reward = null
  onContactReward(reward) {
    if (this.reward === reward) return
    this.reward = reward
    switch (reward.type) {
      case RewardType.TwoShoot:
        AudioMgr.inst.playOneShot(this.twoShootSound, 1)
        this.transitionTwoShoot()
        break
      case RewardType.Bomb:
        AudioMgr.inst.playOneShot(this.bombSound, 1)
        GameManager.getInstance().addBomb()
        break
    }
  }
  transitionTwoShoot() {
    this.shootType = ShootType.TwoShoot
    this.scheduleOnce(() => {
      this.shootType = ShootType.OneShoot
    }, this._TwoShootTime)
  }
  onContactEnemy() {
    if (this.isInvincible) return
    this.isInvincible = true
    this.changeLifeCount(-1)
    if (this.hp > 0) {
      this.animation.play(this.animationHit)
    } else {
      this.shootType = ShootType.None
      this.animation.play(this.animationDown)
      if (this._collider) {
        this._collider.enabled = false
      }
      this.scheduleOnce(() => {
        GameManager.getInstance().gameOver()
      }, 1)
    }
  }
  changeLifeCount(count: number) {
    this.hp += count
    this.lifeCountUI.updateUI(this.hp)
  }
}
